package com.grupit.module.user.web.gwt.client.pluggablefeatures.ui;

import org.ioc.commons.impl.gwt.client.ui.DisplayComposite;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.Import;
import com.google.gwt.resources.client.CssResource.ImportedWithPrefix;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.grupit.api.web.gwt.client.ui.design.widget.MainBoardCenterPanel;
import com.grupit.engine.util.Format;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ioc.NoteBoardView;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ioc.NoteBoardView.Action;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ioc.NoteBoardView.Event;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ioc.NoteBoardView.Operation;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ioc.NoteBoardView.Presenter;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ioc.NoteBoardViewPresenter;
import com.grupit.module.user.web.gwt.client.pluggablefeatures.ui.NoteBoardViewImpl.NoteBoardViewAppearance.NoteBoardViewResources;
import com.seleniti.pozit.controller.ui.widget.PoZitBoardPanel;
import com.seleniti.pozit.web.desktop.client.ui.cell.PoZitCell.PoZitAppearance.PoZitCss;
import com.seleniti.pozit.web.desktop.client.ui.widget.PoZitBoardPanelWidget;
import com.seleniti.pozit.web.desktop.client.ui.widget.PoZitBoardPanelWidget.PoZitBoardPanelAppearance.PoZitBoardPanelCss;

public class NoteBoardViewImpl extends DisplayComposite<Event, Operation, Action, Presenter> implements NoteBoardView {

	private static NoteBoardViewImplUiBinder uiBinder = GWT.create(NoteBoardViewImplUiBinder.class);

	interface NoteBoardViewImplUiBinder extends UiBinder<Widget, NoteBoardViewImpl> {
	}

	public static class NoteBoardViewAppearance extends
			com.grupit.api.web.gwt.client.ui.lookandfeel.Appearance<NoteBoardViewResources> {
		public NoteBoardViewAppearance(NoteBoardViewResources resources) {
			super(resources);
		}

		public static interface NoteBoardViewResources extends ClientBundle {
			@Import({ PoZitBoardPanelCss.class, PoZitCss.class })
			@Source({ NoteBoardViewCss.DEFAULT_CSS })
			NoteBoardViewCss noteBoardView();
		}

		@ImportedWithPrefix("noteBoardView")
		public interface NoteBoardViewCss extends CssResource {
			String DEFAULT_CSS = "NoteBoardViewImpl.css";

			String container();

			String newPozit();

			String minPoZitSize();
		}

		@Override
		public void ensureCssResourcesInjected() {
			this.resources.noteBoardView().ensureInjected();
		}
	}

	@UiField
	PoZitWidget newPozit;

	@UiField(provided = true)
	NoteBoardViewResources theme;

	@UiField
	HTMLPanel container;

	@UiField
	PoZitBoardPanelWidget myNotes;

	@UiField
	MainBoardCenterPanel boardPanels;

	public NoteBoardViewImpl() {
		this.presenter = new NoteBoardViewPresenter(this, eventbus, operationManager, actionController);
		NoteBoardViewAppearance appearance = new NoteBoardViewAppearance(
				GWT.<NoteBoardViewResources> create(NoteBoardViewResources.class));
		this.theme = appearance.getResources();
		initWidget(uiBinder.createAndBindUi(this));
	}

	@UiHandler("newPozit")
	public void onNewPozitMouseDown(MouseDownEvent evt) {
		final Panel container = RootPanel.get();

		final PoZitWidget floatingNewPozit = new PoZitWidget();
		floatingNewPozit.setStyleName(this.theme.noteBoardView().minPoZitSize());

		final Style style = floatingNewPozit.getElement().getStyle();
		style.setPosition(Position.ABSOLUTE);
		style.setLeft(evt.getRelativeX(container.getElement()), Unit.PX);
		style.setTop(evt.getRelativeY(container.getElement()), Unit.PX);

		MouseMoveHandler mouseMoveHandler = new MouseMoveHandler() {

			@Override
			public void onMouseMove(MouseMoveEvent evt) {
				style.setLeft(evt.getRelativeX(container.getElement()), Unit.PX);
				style.setTop(evt.getRelativeY(container.getElement()), Unit.PX);
			}
		};

		floatingNewPozit.addMouseMoveHandler(mouseMoveHandler);

		floatingNewPozit.addMouseUpHandler(new MouseUpHandler() {

			@Override
			public void onMouseUp(MouseUpEvent event) {
				DOM.releaseCapture(floatingNewPozit.getElement());

				Widget myNotesBoardList = myNotes.boardListWidget().asWidget();
				Element myNotesHeading = myNotes.headingElement();
				int xBoardList = event.getRelativeX(myNotesBoardList.getElement());
				int yBoardList = event.getRelativeY(myNotesBoardList.getElement());
				int limitX = myNotesHeading.getOffsetWidth();
				int limitY = myNotesHeading.getOffsetHeight();

				if (xBoardList >= 0 && yBoardList >= 0
						&& xBoardList <= (myNotesBoardList.getOffsetWidth() - floatingNewPozit.getOffsetWidth())
						&& yBoardList <= (myNotesBoardList.getOffsetHeight() - floatingNewPozit.getOffsetHeight())) {
					assert (presenter != null) : Format.substitute(
							"El widget '{0}' necesita tener un presenter asociado. ¿Se te olvidó asignarlo?", this
									.getClass().getName());

					if (xBoardList < limitX && yBoardList < limitY) {
						int diffX = (limitX - xBoardList);
						int diffY = (limitY - yBoardList);
						if (diffX < diffY) {
							xBoardList = limitX;
						} else {
							yBoardList = limitY;
						}
					}

					presenter.onCreatePoZit(xBoardList, yBoardList);
				}

				floatingNewPozit.removeFromParent();
			}
		});

		DOM.setCapture(floatingNewPozit.getElement());
		DOM.eventPreventDefault(DOM.eventGetCurrentEvent());

		container.add(floatingNewPozit);
	}

	@Override
	public PoZitBoardPanel poZitPanel() {
		return this.myNotes;
	}

}
